home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / progs / java.exe / Java WorkShop / data.3 / JWS / examples / checkers / CheckersGame.java < prev    next >
Encoding:
Java Source  |  1997-05-19  |  13.9 KB  |  460 lines

  1. /*
  2.  *        Copyright (C) 1995  Sun Microsystems, Inc
  3.  *                    All rights reserved.
  4.  *          Notice of copyright on this source code 
  5.  *          product does not indicate publication. 
  6.  * 
  7.  * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by 
  8.  * the U.S. Government is subject to restrictions as set forth 
  9.  * in subparagraph (c)(1)(ii) of the Rights in Technical Data
  10.  * and Computer Software Clause at DFARS 252.227-7013 (Oct. 1988) 
  11.  * and FAR 52.227-19 (c) (June 1987).
  12.  *
  13.  *    Sun Microsystems, Inc., 2550 Garcia Avenue,
  14.  *    Mountain View, California 94043.
  15.  */
  16.  
  17. /*
  18.  * @(#) CheckersGame.java 1.4 - last change made 03/17/97
  19.  */
  20.  
  21. import java.awt.*;
  22. import java.applet.*;
  23.  
  24. /**
  25.  * A java implementation of checkers.  Can be run either as a 
  26.  * standalone application or as an applet.
  27.  */
  28. public class CheckersGame extends Applet {
  29.     final int CHECKER_NONE        = 0;
  30.     final int CHECKER_RED         = 1;
  31.     final int CHECKER_BLACK       = 2;
  32.     final int CHECKER_RED_KING    = 3;
  33.     final int CHECKER_BLACK_KING  = 4;
  34.  
  35.     final int SQUARE_RED   = 0;
  36.     final int SQUARE_BLACK = 1;
  37.  
  38.     final int squaresPerSide  = 8;
  39.     final int pixelsPerBoard  = 400;
  40.     final int pixelsPerSquare = 50;
  41.  
  42.     final int MOVE_INVALID = 0;
  43.     final int MOVE_VALID   = 1;
  44.     final int MOVE_HANDLED = 2;
  45.  
  46.     int pieces[][] = new int [squaresPerSide][squaresPerSide];
  47.     int board[][]  = new int [squaresPerSide][squaresPerSide];
  48.  
  49.     Image blackChecker;
  50.     Image redChecker;
  51.     Image blackKingChecker;
  52.     Image redKingChecker;
  53.  
  54.     int clipX = 0,
  55.         clipY = 0,
  56.         clipWidth = this.getSize().width,
  57.         clipHeight = this.getSize().height;
  58.  
  59.     int moving_piece      = CHECKER_NONE;
  60.     int moving_piece_xpos = 0;
  61.     int moving_piece_ypos = 0;
  62.     int moving_piece_x    = -1;
  63.     int moving_piece_y    = -1;
  64.  
  65.     private int sign(int value) {
  66.         if (value > 0) 
  67.             value = 1;
  68.         else if (value < 0) 
  69.             value = -1;
  70.         return value;
  71.     }
  72.  
  73.     private void SetUpdateRegion(int xpos, int ypos) {
  74.         int x1, y1, x2, y2;
  75.         int halfPixelsPerSquare = pixelsPerSquare / 2;
  76.     Dimension d = this.getSize();
  77.  
  78.         x1 = Math.max(0, Math.min (xpos, moving_piece_xpos) - 
  79.             halfPixelsPerSquare);
  80.         y1 = Math.max(0, Math.min (ypos, moving_piece_ypos) - 
  81.             halfPixelsPerSquare);
  82.  
  83.         x2 = Math.min(d.width-1,  Math.max (xpos, moving_piece_xpos) + 
  84.             halfPixelsPerSquare);
  85.         y2 = Math.min(d.height-1, Math.max (ypos, moving_piece_ypos) + 
  86.             halfPixelsPerSquare);
  87.  
  88.         clipX      = x1;
  89.         clipY      = y1;
  90.         clipWidth  = x2 - x1;
  91.         clipHeight = y2 - y1;
  92.     }
  93.  
  94.     private int validMove(int piece, int oldX, int oldY, int newX, int newY) {
  95.         int dx = newX - oldX;
  96.         int dy = newY - oldY;
  97.  
  98.         // Keep the pieces on the board please!
  99.         if (newX < 0 || newX >= squaresPerSide ||
  100.             newY < 0 || newY >= squaresPerSide)
  101.             return MOVE_INVALID;
  102.  
  103.         // We play on black squares only!
  104.         if (board[newY][newX] == SQUARE_RED)
  105.             return MOVE_INVALID;
  106.  
  107.         // Can't move to a square that's already occupied.
  108.         if (pieces[newY][newX] != CHECKER_NONE)
  109.             return MOVE_INVALID;
  110.  
  111.         switch (piece) {
  112.         default:
  113.         case CHECKER_NONE:
  114.             return MOVE_INVALID;
  115.  
  116.         case CHECKER_RED: 
  117.             // Red pieces can only go forward, positive dy's
  118.             if (dy < 1)
  119.                 return MOVE_INVALID;
  120.  
  121.             // Is this a valid one square move.
  122.             if (Math.abs(dx) == 1 && dy == 1) {
  123.                 // When we reach the other end of the board,
  124.                 // we get kinged.
  125.                 if (newY == (squaresPerSide - 1)) {
  126.                     pieces[newY][newX] = CHECKER_RED_KING;
  127.                     return MOVE_HANDLED;
  128.                 } else { 
  129.                     return MOVE_VALID;
  130.                 }
  131.             }
  132.  
  133.             // Is this a valid jump?
  134.             if (Math.abs(dx) == 2 && dy == 2) {
  135.                 // A two square move must be over an opposiing player 
  136.                 if (pieces[oldY+1][oldX+sign(dx)] != CHECKER_BLACK &&
  137.                     pieces[oldY+1][oldX+sign(dx)] != CHECKER_BLACK_KING) 
  138.                     return MOVE_INVALID;
  139.  
  140.                 // take the opposing player's piece off the board.
  141.                 pieces[oldY+1][oldX+sign(dx)] = CHECKER_NONE;
  142.  
  143.                 // When we reach the other end of the board,
  144.                 // we get kinged.
  145.                 if (newY == (squaresPerSide - 1)) {
  146.                     pieces[newY][newX] = CHECKER_RED_KING;
  147.                     return MOVE_HANDLED;
  148.                 }
  149.  
  150.                 return MOVE_VALID;
  151.             }
  152.             break;
  153.         case CHECKER_BLACK:
  154.             // Black pieces can only go forward, negative dy's
  155.             if (dy > -1)
  156.                 return MOVE_INVALID;
  157.  
  158.             // Is this a valid one square move.
  159.             if (Math.abs(dx) == 1 && dy == -1) {
  160.                 // When we reach the other end of the board,
  161.                 // we get kinged.
  162.                 if (newY == 0) {
  163.                     pieces[newY][newX] = CHECKER_BLACK_KING;
  164.                     return MOVE_HANDLED;
  165.                 } else { 
  166.                     return MOVE_VALID;
  167.                 }
  168.             }
  169.  
  170.             // Is this a valid jump?
  171.             if (Math.abs(dx) == 2 && dy == -2) {
  172.                 // A two square move must be over an opposiing player 
  173.                 if (pieces[oldY-1][oldX+sign(dx)] != CHECKER_RED &&
  174.                     pieces[oldY-1][oldX+sign(dx)] != CHECKER_RED_KING) 
  175.                     return MOVE_INVALID;
  176.  
  177.                 // take the opposing player's piece off the board.
  178.                 pieces[oldY-1][oldX+sign(dx)] = CHECKER_NONE;
  179.  
  180.                 // When we reach the other end of the board,
  181.                 // we get kinged.
  182.                 if (newY == 0) {
  183.                     pieces[newY][newX] = CHECKER_BLACK_KING;
  184.                     return MOVE_HANDLED;
  185.                 }
  186.                 return MOVE_VALID;
  187.             }
  188.             break;
  189.         case CHECKER_RED_KING:
  190.             if (Math.abs(dx) == 1 && Math.abs(dy) == 1) {
  191.                 return MOVE_VALID;
  192.             }
  193.  
  194.             if (Math.abs(dx) == 2 && Math.abs(dy) == 2) {
  195.                 if (pieces[oldY+sign(dy)][oldX+sign(dx)] == CHECKER_BLACK) {
  196.                     pieces[oldY+sign(dy)][oldX+sign(dx)] = CHECKER_NONE;
  197.                     return MOVE_VALID;
  198.                 } else if (pieces[oldY+sign(dy)][oldX+sign(dx)] == 
  199.                     CHECKER_BLACK_KING) {
  200.                     pieces[oldY+sign(dy)][oldX+sign(dx)] = CHECKER_NONE;
  201.                     return MOVE_VALID;
  202.                 } else {
  203.                     return MOVE_INVALID;
  204.                 }
  205.             }
  206.             break;
  207.         case CHECKER_BLACK_KING:
  208.             if (Math.abs(dx) == 1 && Math.abs(dy) == 1) {
  209.                 return MOVE_VALID;
  210.             }
  211.  
  212.             if (Math.abs(dx) == 2 && Math.abs(dy) == 2) {
  213.                 if (pieces[oldY+sign(dy)][oldX+sign(dx)] == CHECKER_RED) {
  214.                     pieces[oldY+sign(dy)][oldX+sign(dx)] = CHECKER_NONE;
  215.                     return MOVE_VALID;
  216.                 } else if (pieces[oldY+sign(dy)][oldX+sign(dx)] == 
  217.                     CHECKER_RED_KING) {
  218.                     pieces[oldY+sign(dy)][oldX+sign(dx)] = CHECKER_NONE;
  219.                     return MOVE_VALID;
  220.                 } else {
  221.                     return MOVE_INVALID;
  222.                 }
  223.             }
  224.             break;
  225.         }
  226.         return MOVE_INVALID;
  227.     }
  228.  
  229.     /**
  230.      * The initialization method for an applet
  231.      */
  232.     public void init () {
  233.         int xcolor = 0;
  234.         int ycolor = 0;
  235.         int x, y;
  236.  
  237.         blackChecker = getImage(getCodeBase(), "blackChecker.gif");
  238.         redChecker   = getImage(getCodeBase(), "redChecker.gif");
  239.         blackKingChecker = getImage(getCodeBase(), "blackCheckerKing.gif");
  240.         redKingChecker   = getImage(getCodeBase(), "redCheckerKing.gif");
  241.  
  242.         for (x=0; x < squaresPerSide; x++) {
  243.             ycolor = xcolor % 2;
  244.             for (y=0; y < squaresPerSide; y++) {
  245.                 board[y][x] = ((ycolor % 2) == 1) ? SQUARE_BLACK : SQUARE_RED;
  246.                 ycolor++;
  247.             }
  248.             xcolor++;
  249.         }
  250.         for (x = 0; x < squaresPerSide; x++) {
  251.             for (y = 0; y < squaresPerSide; y++) {
  252.                 pieces[y][x] = CHECKER_NONE;
  253.             }
  254.         }
  255.         for (y = 0; y < 3; y++) {
  256.             for (x = 1 - (y % 2); x < squaresPerSide; x=x+2) {
  257.                 pieces[y][x] = CHECKER_RED;
  258.             }
  259.         }
  260.         for (y = squaresPerSide - 3; y < squaresPerSide; y++) {
  261.             for (x = 1 - (y % 2); x < squaresPerSide; x=x+2) {
  262.                 pieces[y][x] = CHECKER_BLACK;
  263.             }
  264.         }
  265.         resize(pixelsPerBoard, pixelsPerBoard);
  266.     }
  267.  
  268.     /**
  269.      * draws the checkerboard
  270.      * @param g the graphics object
  271.      */
  272.     public void paint(Graphics g) {
  273.         int xpos, ypos, x, y;
  274.         Color redColor = Color.red;
  275.         Color blackColor = Color.black;
  276.     Dimension d = this.getSize();
  277.  
  278.         for (x=0; x < squaresPerSide; x++) {
  279.             for (y=0; y < squaresPerSide; y++) {
  280.                 switch (board[y][x]) {
  281.                 case SQUARE_RED:
  282.                     g.setColor(redColor);
  283.                     break;
  284.                 default:
  285.                     g.setColor(blackColor);
  286.                     break;
  287.                 }
  288.                 xpos = x * pixelsPerSquare;
  289.                 ypos = y * pixelsPerSquare;
  290.                 g.fillRect (xpos, ypos, pixelsPerSquare, pixelsPerSquare);
  291.             }
  292.         }
  293.  
  294.         for (x=0; x < squaresPerSide; x++) {
  295.             for (y=0; y < squaresPerSide; y++) {
  296.                 xpos = x * pixelsPerSquare;
  297.                 ypos = y * pixelsPerSquare;
  298.                 switch (pieces[y][x]) {
  299.                 case CHECKER_NONE:
  300.                     break;
  301.                 case CHECKER_RED:
  302.                     g.drawImage(redChecker, xpos, ypos, this);
  303.                     break;
  304.                 case CHECKER_BLACK:
  305.                     g.drawImage(blackChecker, xpos, ypos, this);
  306.                     break;
  307.                 case CHECKER_RED_KING:
  308.                     g.drawImage(redKingChecker, xpos, ypos, this);
  309.                     break;
  310.                 case CHECKER_BLACK_KING:
  311.                     g.drawImage(blackKingChecker, xpos, ypos, this);
  312.                     break;
  313.                 default:
  314.                     break;
  315.                 }
  316.             }
  317.         }
  318.  
  319.         xpos = moving_piece_xpos - pixelsPerSquare / 2;
  320.         ypos = moving_piece_ypos - pixelsPerSquare / 2;
  321.  
  322.         switch (moving_piece) {
  323.         case CHECKER_NONE:
  324.             break;
  325.         case CHECKER_RED:
  326.             g.drawImage(redChecker, xpos, ypos, this);
  327.             break;
  328.         case CHECKER_BLACK:
  329.             g.drawImage(blackChecker, xpos, ypos, this);
  330.             break;
  331.         case CHECKER_RED_KING:
  332.             g.drawImage(redKingChecker, xpos, ypos, this);
  333.             break;
  334.         case CHECKER_BLACK_KING:
  335.             g.drawImage(blackKingChecker, xpos, ypos, this);
  336.             break;
  337.         default:
  338.             break;
  339.         }
  340.  
  341.         clipX = 0;
  342.         clipY = 0;
  343.         clipWidth = d.width;
  344.         clipHeight = d.height;
  345.     }
  346.  
  347.     /**
  348.      * updates the checkerboard display
  349.      * @param g the graphics object
  350.      */
  351.     public void update(Graphics g) {
  352.         g.clipRect (clipX, clipY, clipWidth, clipHeight);
  353.         paint(g);
  354.     }
  355.  
  356.     /**
  357.      * process a mouse down event
  358.      * @param evt the event
  359.      * @param xpos the x coordinate of the event
  360.      * @param ypos the y coordinate of the event
  361.      */
  362.     public boolean mouseDown(java.awt.Event evt, int xpos, int ypos) {
  363.         int x = xpos / pixelsPerSquare;
  364.         int y = ypos / pixelsPerSquare;
  365.  
  366.         if (x >= 0 && x < squaresPerSide && 
  367.             y >= 0 && y < squaresPerSide) {
  368.  
  369.             if (pieces[y][x] != CHECKER_NONE) {
  370.                 moving_piece = pieces[y][x];
  371.                 pieces[y][x] = CHECKER_NONE;
  372.                 moving_piece_xpos = xpos;
  373.                 moving_piece_ypos = ypos;
  374.                 moving_piece_x = x;
  375.                 moving_piece_y = y;
  376.                 repaint();
  377.             } else {
  378.                 moving_piece = CHECKER_NONE;
  379.             }
  380.         }
  381.     return true;
  382.     }
  383.  
  384.     /**
  385.      * process a mouse up event
  386.      * @param evt the event
  387.      * @param xpos the x coordinate of the event
  388.      * @param ypos the y coordinate of the event
  389.      */
  390.     public boolean mouseUp(java.awt.Event evt, int xpos, int ypos) {
  391.         int x = xpos / pixelsPerSquare;
  392.         int y = ypos / pixelsPerSquare;
  393.         int moveStatus;
  394.  
  395.         if (moving_piece == CHECKER_NONE)
  396.             return false;
  397.  
  398.         moveStatus = validMove(moving_piece, moving_piece_x, moving_piece_y, 
  399.             x, y);
  400.         switch (moveStatus) {
  401.         case MOVE_VALID:
  402.             pieces[y][x] = moving_piece;
  403.             break;
  404.         case MOVE_INVALID:
  405.             pieces[moving_piece_y][moving_piece_x] = moving_piece;
  406.             break;
  407.         case MOVE_HANDLED:
  408.         default:
  409.             break;
  410.         }
  411.         moving_piece = CHECKER_NONE;
  412.         repaint();
  413.  
  414.     return true;
  415.     }
  416.  
  417.     /**
  418.      * process a mouse exit event
  419.      */
  420.     public void mouseExit() {
  421.         if (moving_piece == CHECKER_NONE)
  422.             return;
  423.  
  424.         pieces[moving_piece_y][moving_piece_x] = moving_piece;
  425.         moving_piece = CHECKER_NONE;
  426.         repaint();
  427.     }
  428.  
  429.     /**
  430.      * process a mouse drag event
  431.      */
  432.     public boolean mouseDrag(java.awt.Event evt, int xpos, int ypos) {
  433.  
  434.         if (moving_piece == CHECKER_NONE)
  435.             return false;
  436.  
  437.         SetUpdateRegion(xpos, ypos);
  438.  
  439.         moving_piece_xpos = xpos;
  440.         moving_piece_ypos = ypos;
  441.          
  442.         repaint();
  443.     return true;
  444.     }
  445.  
  446.     /* 
  447.      * The main routine for a standalone program.
  448.      */
  449.     public static void main(String args[]) {
  450.     Frame f = new Frame("Checkers game");
  451.     CheckersGame app = new CheckersGame();
  452.     app.init();
  453.     app.start();
  454.  
  455.     f.add("Center", app);
  456.     f.setSize(300, 300);
  457.     f.show();
  458.     }
  459. }
  460.